package com.example.eddy.customcircleview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Created by Eddy on 26/4/2017.
 */

public class CircleImageView extends ImageView {
    //缩放类型
    private final ScaleType SCALE_TYPE=ScaleType.CENTER_CROP;
    //边框默认颜色
    private final int DEFAULT_BORDER_COLOR=Color.BLACK;
    //边框默认宽度
    private final  int DEFAULT_BORDER_WIDTH=0;
    private final  boolean DEFAULT_BORDER_OVERLAY=false;

    //矩形圆角默认大小
    private final int DEFALUT_CIRCLE_CORNER=0;

   //矩形圆角大小
    private int circle_corner;

    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 2;

    private int mBorderWidth=DEFAULT_BORDER_WIDTH;
    private int mBorderColor=DEFAULT_BORDER_COLOR;
    private boolean mBorderOverlay=DEFAULT_BORDER_OVERLAY;
    private final Matrix mShaderMatrix = new Matrix();
    private RectF mBorderRect=new RectF();
    private RectF mDrawableRect=new RectF();
    //图片半径
    private float mDrawableRadius;
    //带边框的图片半径
    private float mBorderRadius;

    //是否执行了构造函数
    private boolean mReady;
    //是否执行setup方法
    private boolean mSetupPending;

    private Bitmap mBitmap;

    private BitmapShader mBitmapShader;
    //这个画笔最为重要的是关联了mBitmapShader使canvas在执行的时候可以切割原图片（mBitmapShader是关联了原图的bitmap）
    private final Paint mBitmapPaint=new Paint();//图片画笔
    //这个描边，则与本身的原图bitmap没有任何关联
    private final Paint mBorderPaint=new Paint();//边界画笔

    private int mBitmapHeight;//位图高度
    private int mBitmapWidth;//位图宽度



    public CircleImageView(Context context) {
        super(context);
        init();
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        this(context,attrs,0);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            this(context,attrs,defStyleAttr,0);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.CircleImageView,defStyleAttr,defStyleRes);
        mBorderColor=array.getColor(R.styleable.CircleImageView_border_color,DEFAULT_BORDER_COLOR);
        mBorderWidth=array.getDimensionPixelSize(R.styleable.CircleImageView_border_width,DEFAULT_BORDER_WIDTH);
        mBorderOverlay=array.getBoolean(R.styleable.CircleImageView_border_overlay,DEFAULT_BORDER_OVERLAY);
        circle_corner=array.getDimensionPixelSize(R.styleable.CircleImageView_circel_corner,DEFALUT_CIRCLE_CORNER);
        array.recycle();
        init();
    }

    private void init(){
        super.setScaleType(SCALE_TYPE);
        /**
         *  保证第一次执行setup函数，要在构造函数执行完调用
         */
        mReady=true;
        if(mSetupPending){
            setUp();
            mSetupPending=false;
        }
    }

    /**
     * 此种ImageView只支持CENTER_CROP这一种属性
     * @param scaleType
     */
    @Override
    public void setScaleType(ScaleType scaleType) {
       if(scaleType!=SCALE_TYPE){
           throw new IllegalArgumentException(String.format("ScaleType is not support "+SCALE_TYPE));
       }
    }

    @Override
    public void setAdjustViewBounds(boolean adjustViewBounds) {
       if(adjustViewBounds){
           throw  new IllegalArgumentException(String.format("adjustViewBounds not support"));
       }
    }


    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        mBitmap=bm;
        setUp();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap=getBitmapFromDrawable(drawable);
        setUp();
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        mBitmap=getBitmapFromDrawable(getDrawable());
        setUp();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        mBitmap=getBitmapFromDrawable(getDrawable());
        setUp();
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setUp();
    }
    public int getBorderColor() {
        return mBorderColor;
    }

    public void setBorderColor(int borderColor) {
        if (borderColor == mBorderColor) {
            return;
        }

        mBorderColor = borderColor;
        mBorderPaint.setColor(mBorderColor);
        invalidate();
    }

    public void setBorderColorResource(int borderColorRes) {
        setBorderColor(getContext().getResources().getColor(borderColorRes));
    }

    public int getBorderWidth() {
        return mBorderWidth;
    }

    public void setBorderWidth(int borderWidth) {
        if (borderWidth == mBorderWidth) {
            return;
        }

        mBorderWidth = borderWidth;
        setUp();
    }

    public boolean isBorderOverlay() {
        return mBorderOverlay;
    }

    public void setBorderOverlay(boolean borderOverlay) {
        if (borderOverlay == mBorderOverlay) {
            return;
        }

        mBorderOverlay = borderOverlay;
        setUp();
    }
    /**
     * 初始化paint，构造渲染器BitmapShader用bitmap来填充绘制区域，设置样式以及内外圆半径计算等。
     */
    private void setUp(){
        //判断此时构造函数是否已经执行，也即是mReady是否为true
        if(!mReady){
            mSetupPending=true;
            return;
        }

        if(mBitmap==null) return;
        /**
         * 渲染的三种模式：
         * 1.Shader.TileMode.CLAMP：边缘拉伸
         * 2.
         */
        mBitmapShader=new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        //设置图片反锯齿和渲染器
        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setShader(mBitmapShader);
        //设置边界画笔样式
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);

        //获取图片原始宽高
        mBitmapHeight=mBitmap.getHeight();
        mBitmapWidth=mBitmap.getWidth();
        //设置含边界的显示区域
        mBorderRect.set(0,0,getWidth(),getHeight());

        mBorderRadius=Math.min((mBorderRect.height()-mBorderWidth)/2,(mBorderRect.width()-mBorderWidth)/2);
        mDrawableRect.set(mBorderRect);
        if(!mBorderOverlay){
            mDrawableRect.inset(mBorderWidth,mBorderWidth);
        }
        mDrawableRadius=Math.min(mDrawableRect.height()/2,mDrawableRect.width()/2);
        //设置渲染器的变换矩阵 也即是mBitmap用何种缩放形式填充
        updateShaderMatrix();
        //手动出发onDraw（）函数 完成最终的绘制
        invalidate();
    }

    /**
     * 设置BitmapShader的Matrix参数，设置最小缩放比例，平移参数；保证图片损失度最小和始终绘制图片正中央的那部分
     */
    private void updateShaderMatrix(){
        float scale;
        float dx=0;
        float dy=0;
        mShaderMatrix.set(null);
        //这个判断条件就是为了取得最小的缩放比例，相当于 （mBitmapWidth/mDrawableRect.width()>mBitmapHeight/mDrawableRect.height()）
        if(mBitmapWidth*mDrawableRect.height()>mDrawableRect.width()*mBitmapHeight){
            //y轴缩放，x轴平移 使得图片的y轴方向的边的尺寸缩放到图片的显示区域
            scale=mDrawableRect.height()/(float) mBitmapHeight;
            dx=(mDrawableRect.height()-mBitmapHeight*scale)*0.5f;
        }else {
        //            x轴缩放，y轴平移
            scale=mDrawableRect.width()/(float) mBitmapWidth;
            dy=(mDrawableRect.height()-mBitmapHeight*scale)*0.5f;
        }
        //        shader的变换矩阵，这里主要主要用于放大或者缩小
        mShaderMatrix.setScale(scale,scale);
        //平移
        mShaderMatrix.postTranslate((int)(dx+0.5f)+mDrawableRect.left,(int)(dy+0.5f)+mDrawableRect.top);
        //设置变换矩阵
        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //没有设置图片就不画
        if(getDrawable()==null){
            return;
        }
        //没有圆角，直接画圆
        if(circle_corner==0){
            //绘制内圆形，参数内圆半径，图片画笔为mBitmapPaint
            canvas.drawCircle(getWidth()/2,getHeight()/2,mDrawableRadius,mBitmapPaint);
            //如果圆形边缘的宽度不为0，还要绘制边界 参数：外圆半径 边界画笔为mBorderPaint
            if(mBorderWidth!=0){
                canvas.drawCircle(getWidth()/2,getHeight()/2,mBorderRadius,mBorderPaint);
            }
        }else {
            canvas.drawRoundRect(new RectF(mDrawableRect),circle_corner,circle_corner,mBitmapPaint);
            if(mBorderWidth!=0){
              canvas.drawRoundRect(new RectF(mDrawableRect),circle_corner,circle_corner,mBorderPaint);
            }
        }

    }

    /**
     * drawable转bitmap
     * @param drawable
     * @return
     */
    private Bitmap getBitmapFromDrawable(Drawable drawable){
            if(drawable==null)return null;
            if(drawable instanceof BitmapDrawable){
                return ((BitmapDrawable) drawable).getBitmap();
            }
        try {
            Bitmap bitmap;

            if (drawable instanceof ColorDrawable) {
                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
            } else {
                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
            }
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (OutOfMemoryError e) {
            return null;
        }
    }
}
